package csm.sql;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * 각 DBMS에 맞는 데이터베이스 커넥션을 생성하는 추상클래스입니다.
 * @author seungmun
 * @since 2006.1.18.
 * @version
 * @see
 */
public abstract class ConnectionFactory
{
	/**
	 * 이 커넥션풀을 생성하는데 사용한 접속정보를 구분하는 이름입니다.
	 */
	protected String connectionName = "default";

	/**
	 * 이 커넥션풀을 생성하는데 사용한 접속정보를 구분하는 이름을 가져옵니다.
	 * @return
	 */
	public String getConnectionName()
	{
		return connectionName;
	}
	
	/**
	 * 커넥션 풀을 생성하는데 필요한 접속정보를 구분하는 이름을 설정합니다.
	 * @param connectionName
	 */
	protected void setConnectionName(String connectionName)
	{
		this.connectionName = connectionName;
	}

	/**
	 * "default" 설정을 이용하여, 커넥션 풀 객체를 생성하고 가져옵니다.
	 * @return
	 * @throws SQLException
	 */
	public static ConnectionFactory newInstance() throws SQLException
	{
		return newInstance("default");
	}

	/**
	 * 지정한 설정을 이용하여, 커넥션 풀 객체를 생성하고 가져옵니다.
	 * @param connectionName 설정을 구분하는 구분명.
	 * @return
	 * @throws SQLException
	 */
	public static ConnectionFactory newInstance(String connectionName) throws SQLException
	{
		String connectionPool = DBConfig.getDBConfig(connectionName).getSettings("connection.pool");
		try
		{
			Class<? extends ConnectionFactory> clazz = Class.forName(connectionPool).asSubclass(ConnectionFactory.class);
			ConnectionFactory obj = clazz.newInstance();
			if (obj != null) obj.setConnectionName(connectionName);

			obj.createConnectionPool();

			return obj;
		}
		catch (InstantiationException e)
		{
			throw new SQLException(e.getMessage());
		}
		catch (IllegalAccessException e)
		{
			throw new SQLException(e.getMessage());
		}
		catch (ClassNotFoundException e)
		{
			throw new SQLException(e.getMessage());
		}
	}

	/**
	 * 커넥션풀을 생성합니다.
	 * @throws SQLException
	 */
	protected abstract void createConnectionPool() throws SQLException;

	/**
	 * 커넥션풀에서 커넥션을 가져옵니다.
	 * 
	 * @return Connection
	 */
	public abstract Connection getConnection() throws SQLException;

	/**
	 * 커넥션 풀을 닫습니다.
	 */
	public abstract void closeConnectionPool() throws SQLException;

	/**
	 * Max 값을 가져오는 쿼리를 반환합니다.
	 * @param table
	 * @param column
	 * @param where
	 * @return
	 */
	public String createMaxQuery(String table, String column, String where)
	{
		StringBuffer sb = new StringBuffer(String.format("SELECT NVL(MAX(%s)+1, 1) FROM %s ", column, table));
		if (where != null && where.trim().length() > 0) sb.append("WHERE ").append(where);
		return sb.toString();
	}

}
